PROJ	:=
EMPTY	:=
SPACE	:= $(EMPTY) $(EMPTY)
SLASH	:= /
DUMP	:= dump

V       := @

# ARCH	:= arch/arm/s3c2410/
ARCH	:= 

SKYEYE := skyeye
QEMU   := qemu-system-arm

#GCCPREFIX := arm-elf-
GCCPREFIX := arm-linux-

# eliminate default suffix rules
.SUFFIXES: .c .S .h

# delete target files if there is an error (or make is interrupted)
.DELETE_ON_ERROR:

# define compiler and flags

HOSTCC		:= gcc
HOSTCFLAGS	:= -g -Wall -O2

GDB		:= $(GCCPREFIX)gdb

CC		:= $(GCCPREFIX)gcc
CFLAGS	:= -mcpu=arm926ej-s -fno-builtin -Wall -ggdb -gstabs -nostdinc -nostartfiles $(DEFS)
CFLAGS	+= $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector)
CTYPE	:= c S

LD      := $(GCCPREFIX)ld
LDFLAGS	:= 
LDFLAGS	+= -nostdlib 

OBJCOPY := $(GCCPREFIX)objcopy
OBJDUMP := $(GCCPREFIX)objdump

COPY	:= cp
MKDIR   := mkdir -p
MV		:= mv
RM		:= rm -f
AWK		:= awk
SED		:= sed
SH		:= sh
TR		:= tr
TOUCH	:= touch -c

OBJDIR	:= obj
BINDIR	:= bin

ARCHIVE := -L/opt/FriendlyARM/toolschain/4.4.3/lib/gcc/arm-none-linux-gnueabi/4.4.3/
#ARCHIVE := -L/usr/local/CodeSourcery/Sourcery_G++_Lite/lib/gcc/arm-none-linux-gnueabi/4.5.2/
LIBRARY := $(ARCHIVE)  -lgcc

ALLOBJS	:=
ALLDEPS	:=
TARGETS	:=

USER_PREFIX	:= __user_

include tools/function.mk

listf_cc = $(call listf,$(1),$(CTYPE))

# for cc
add_files_cc = $(call add_files,$(1),$(CC),$(CFLAGS) $(3),$(2),$(4))
create_target_cc = $(call create_target,$(1),$(2),$(3),$(CC),$(CFLAGS))

# for hostcc
add_files_host = $(call add_files,$(1),$(HOSTCC),$(HOSTCFLAGS),$(2),$(3))
create_target_host = $(call create_target,$(1),$(2),$(3),$(HOSTCC),$(HOSTCFLAGS))

cgtype = $(patsubst %.$(2),%.$(3),$(1))
objfile = $(call toobj,$(1))
asmfile = $(call cgtype,$(call toobj,$(1)),o,asm)
outfile = $(call cgtype,$(call toobj,$(1)),o,out)
symfile = $(call cgtype,$(call toobj,$(1)),o,sym)
filename = $(basename $(notdir $(1)))
ubinfile = $(call outfile,$(addprefix $(USER_PREFIX),$(call filename,$(1))))

# for match pattern
match = $(shell echo $(2) | $(AWK) '{for(i=1;i<=NF;i++){if(match("$(1)","^"$$(i)"$$")){exit 1;}}}'; echo $$?)

# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
# include kernel/user

INCLUDE	+= libs/

CFLAGS	+= $(addprefix -I,$(INCLUDE))

LIBDIR	+= libs

#BOARD ?=at91
BOARD :=versatilepb
QEMU_IMG := $(BINDIR)/sim_$(BOARD).img
AT91_IMG := $(BINDIR)/$(BOARD).img
PLATFORM_DEF := -DPLATFORM_$(shell echo $(BOARD) | tr 'a-z' 'A-Z') 
#PLATFORM_DEF := -DPLATFORM_AT91

$(call add_files_cc,$(call listf_cc,$(LIBDIR)),libs,)

# -------------------------------------------------------------------
# user programs

UINCLUDE	+= user/include/ \
			   user/libs/

USRCDIR		+= user

ULIBDIR		+= user/libs

UCFLAGS		+= $(addprefix -I,$(UINCLUDE))
USER_BINS	:=

$(call add_files_cc,$(call listf_cc,$(ULIBDIR)),ulibs,$(UCFLAGS))
$(call add_files_cc,$(call listf_cc,$(USRCDIR)),uprog,$(UCFLAGS))

UOBJS	:= $(call read_packet,ulibs libs)

define uprog_ld
__user_bin__ := $$(call ubinfile,$(1))
USER_BINS += $$(__user_bin__)
$$(__user_bin__): tools/user.ld
$$(__user_bin__): $$(UOBJS)
$$(__user_bin__): $(1) | $$$$(dir $$$$@)
	@echo + ld $$@
	$(V)$(LD) $(LDFLAGS) -T tools/user.ld -o $$@ $$(UOBJS) $(1)
	$(V)$(OBJDUMP) -S $$@ > $$(call cgtype,$$<,o,asm)
	$(V)$(OBJDUMP) -t $$@ | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$$$/d' > $$(call cgtype,$$<,o,sym)
	$(V)$(OBJCOPY) -S -I elf32-littlearm -O elf32-littlearm $$@ $$@
	$(V)$(OBJCOPY) -I binary -O elf32-littlearm -B arm $$@ $$@
endef

$(foreach p,$(call read_packet,uprog),$(eval $(call uprog_ld,$(p))))

# -------------------------------------------------------------------
# kernel

KINCLUDE	+= kern/debug/ \
				$(ARCH)kern/driver/ \
				$(ARCH)kern/trap/ \
				$(ARCH)kern/mm/ \
				$(ARCH)kern/ \
				$(ARCH)kern/mach \
				kern/libs/ \
				$(ARCH)kern/sync/ \
			    kern/fs/ \
			    kern/process/ \
			    kern/schedule/ \
			   kern/syscall 

KSRCDIR		+= kern/init \
				kern/libs \
				kern/debug \
				$(ARCH)kern/driver \
				$(ARCH)kern/trap \
				$(ARCH)kern/mm \
				$(ARCH)kern/sync \
				$(ARCH)kern/mach \
			    kern/fs \
			    kern/process \
			    kern/schedule \
			   kern/syscall

KCFLAGS		+= $(addprefix -I,$(KINCLUDE))
KCFLAGS   += $(PLATFORM_DEF)

$(call add_files_cc,$(call listf_cc,$(KSRCDIR)),kernel,$(KCFLAGS))

KOBJS	= $(call read_packet,kernel libs)

# create kernel target
kernel	= $(call totarget,kernel)

$(kernel): tools/kernel-$(BOARD).ld

$(kernel): $(KOBJS) $(USER_BINS)
	@echo + ld $@
	$(V)$(LD) $(LDFLAGS) -T tools/kernel-$(BOARD).ld -o $@ $(KOBJS) -b elf32-littlearm $(USER_BINS) $(LIBRARY)
	$(V)$(OBJDUMP) -S $@ > $(call asmfile,kernel)
	$(V)$(OBJDUMP) -t $@ | $(SED) '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > $(call symfile,kernel)

$(call create_target,kernel)

# -------------------------------------------------------------------

# create bootblock
bootfiles = $(call listf_cc,$(ARCH)boot)
$(foreach f,$(bootfiles),$(call cc_compile,$(f),$(CC),$(CFLAGS) -Os -I./kern/mach -nostdinc $(PLATFORM_DEF)))

bootblock = $(call totarget,bootblock)

$(bootblock): $(call toobj,$(bootfiles))
	@echo + ld $@
	$(V)$(LD) $(LDFLAGS) -N -e _start -T$(ARCH)boot/bootlink-$(BOARD).lds $^ -o $(call toobj,bootblock)
	$(V)$(OBJDUMP) -S $(call objfile,bootblock) > $(call asmfile,bootblock)
	$(V)$(OBJCOPY) -S -O elf32-littlearm $(call objfile,bootblock) $(bootblock)
	
$(call create_target,bootblock)

# -------------------------------------------------------------------


# create ucore.img
#UCOREIMG        := $(call totarget,ucore.img)

#$(UCOREIMG): $(kernel) $(bootblock)
#	$(V)dd if=/dev/zero of=$@ count=10000
#	$(V)dd if=$(bootblock) of=$@ conv=notrunc
#	$(V)dd if=$(kernel) of=$@ seek=1 conv=notrunc

#$(call create_target,ucore.img)

# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>


$(call finish_all)

ifneq ($(MAKECMDGOALS),clean)
-include $(ALLDEPS)
endif

TARGETS: $(TARGETS)

.DEFAULT_GOAL := TARGETS

RUN_PREFIX	:= _binary_$(OBJDIR)_$(USER_PREFIX)

.PHONY: $(SKYEYE)
$(SKYEYE):
	$(SKYEYE) -e $(bootblock)
	
.PHONY: $(DUMP)
$(DUMP):
	arm-elf-objdump -S bin/kernel > $(DUMP).txt && gedit $(DUMP).txt&

.PHONY: test
test:
	$(MAKE) clean
	$(MAKE)
	$(MAKE) $(SKYEYE)
	
test-%:
	$(MAKE) clean
	$(MAKE) $(MAKEOPTS) "DEFS+=-DTEST=$* -DTESTSTART=$(RUN_PREFIX)$*_out_start -DTESTSIZE=$(RUN_PREFIX)$*_out_size"
	$(MAKE) $(SKYEYE)

.PHONY: run
run:
	$(MAKE) clean
	$(MAKE) 
	$(SKYEYE) -n -e $(bootblock)
	
touch:
	$(V)$(foreach f,$(TOUCH_FILES),$(TOUCH) $(f))

.PHONY: clean
clean:
	-$(RM) -r $(OBJDIR) $(BINDIR) ./$(DUMP).txt



$(OBJDIR)/piggy.o: boot/image/piggy.S $(BINDIR)/kernel
	$(CC) $(CFLAGS) -c -o $@ boot/image/piggy.S

$(QEMU_IMG):  $(TARGETS) $(OBJDIR)/piggy.o
	$(LD) -T boot/image/qemu.ld -o $(QEMU_IMG)  $(call toobj,$(bootfiles)) $(OBJDIR)/piggy.o


.PHONY: qemu
qemu: $(QEMU_IMG)
	qemu-system-arm  -M $(BOARD) -m 16M  -kernel $(QEMU_IMG) -serial stdio

.PHONY: 
qemu_debug: $(QEMU_IMG)
	qemu-system-arm -M $(BOARD) -S -s -m 16M -kernel $(QEMU_IMG) -serial stdio

.PHONY: qdebug
debug: $(TARGETS)
	gnome-terminal -e "make qemu_debug"
	sleep 1
	$(GDB)

$(AT91_IMG):  $(TARGETS) 
	$(OBJCOPY) -S -O binary $(bootblock) $(OBJDIR)/bootblock.bin
	dd if=/dev/zero of=$(AT91_IMG) bs=1M count=1 
	dd if=$(OBJDIR)/bootblock.bin of=$(AT91_IMG) conv=notrunc
	dd if=$(BINDIR)/kernel of=$(AT91_IMG) seek=8 conv=notrunc
	mkimage -A arm -O linux -T kernel -C none -a 0x73f00000 -e 0x73f00000 -n "ucore-arm" -d $(AT91_IMG) $(BINDIR)/at91-image
	cp $(BINDIR)/at91-image /media/PIA_boot/image.bin

.PHONY: at91
at91: $(AT91_IMG)

